package vip.liux.contracts.models.coupon;

import org.apache.commons.lang3.math.NumberUtils;
import org.springframework.stereotype.Component;
import org.springframework.util.Assert;
import vip.liux.contracts.repositories.coupon.CouponRepository;
import vip.liux.contracts.repositories.coupon.UserCouponRepository;
import vip.liux.contracts.shared.enums.Status;
import vip.liux.contracts.shared.enums.coupon.UsedTag;
import vip.liux.contracts.shared.value.ReceivedRecord;

import java.time.LocalDateTime;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * 用户优惠券领域服务
 * 负责处理与用户优惠券相关的核心业务逻辑
 */
@Component
public class UserCouponDomainService {
    private final CouponRepository couponRepository;
    private final UserCouponRepository userCouponRepository;

    public UserCouponDomainService(CouponRepository couponRepository, UserCouponRepository userCouponRepository) {
        this.couponRepository = couponRepository;
        this.userCouponRepository = userCouponRepository;
    }

    /**
     * 根据优惠券编号查询优惠券
     *
     * @param couponNo 优惠券编号
     * @return 优惠券对象
     */
    public Coupon findCouponByNo(String couponNo) {
        return couponRepository.findByCouponNo(couponNo)
                .orElseThrow(() -> new IllegalArgumentException("优惠券不存在"));
    }

    /**
     * 校验优惠券是否可领取
     *
     * @param coupon 优惠券对象
     * @param userId 用户ID
     */
    public void checkCoupon(Coupon coupon, Long userId) {
        Assert.notNull(coupon, "优惠券编号不能为空");
        Assert.notNull(userId, "用户编号不能为空");
        // 校验领取时间是否有效
        if (coupon.getReceiveStart() != null && coupon.getReceiveStart().isAfter(LocalDateTime.now())) {
            throw new IllegalArgumentException("未到领取时间");
        }

        if (coupon.getReceiveEnd() != null && coupon.getReceiveEnd().isBefore(LocalDateTime.now())) {
            throw new IllegalArgumentException("已过领取时间");
        }

        // 校验优惠券状态
        if (coupon.getStatus() == Status.DISABLED) {
            throw new IllegalArgumentException("优惠券已禁用");
        }

        // 校验优惠券是否已被领取完
        long receivedCount = userCouponRepository.findCountByCoupon(coupon.getCouponNo());
        if (NumberUtils.compare(coupon.getReceiveNum(), receivedCount) <= 0) {
            throw new IllegalArgumentException("优惠券已领完");
        }

        // 校验用户是否已达到领取上限
        long userReceivedCount = userCouponRepository.findCountByUserIdAndCoupon(userId, coupon.getCouponNo());
        if (NumberUtils.compare(userReceivedCount, coupon.getReceiveNumLimit()) >= 0) {
            throw new IllegalArgumentException("已达到领取上限");
        }
    }

    /**
     * 创建用户优惠券
     *
     * @param coupon 优惠券对象
     * @param userId 用户ID
     * @param code   优惠券编码
     * @return 用户优惠券对象
     */
    public UserCoupon createUserCoupon(Coupon coupon, Long userId, String code) {
        UserCoupon userCoupon = new UserCoupon();
        userCoupon.setCoupon(coupon);
        userCoupon.setUserId(userId);
        userCoupon.setCode(code);
        userCoupon.setReceiveTime(LocalDateTime.now());
        userCoupon.setUsedTag(UsedTag.UNUSED);
        return userCouponRepository.save(userCoupon);
    }

    /**
     * 获取优惠券领取记录
     *
     * @param couponNos 优惠券编号集合
     * @return 优惠券领取记录的映射
     */
    public Map<String, ReceivedRecord> getReceivedRecords(Set<String> couponNos) {
        List<ReceivedRecord> userCoupon = userCouponRepository.findCountUserIdByCouponNoIn(couponNos);
        return userCoupon.stream().collect(
                Collectors.toMap(
                        ReceivedRecord::getCouponNo,
                        r -> r,
                        (existing, replacement) -> existing
                )
        );
    }
}